using Microsoft.EntityFrameworkCore;
using net_work.Common.Request;
using net_work.Common.Result;
using net_work.Config;
using net_work.Data.DTO.Cou;
using net_work.Data.Entity.Cou;
using net_work.Data.Enum.Cou;
using net_work.Data.VO.Cou;
using net_work.IRepository.Cou;

namespace net_work.Repository.Cou;

public class TeachingRepository(ApplicationDbContext dbContext) : Repository<Teaching>(dbContext), ITeachingRepository
{
    public async Task<long> InsertAsync(TeachingAddRequest teachingAddRequest)
    {
        var existingTeaching =
            await dbContext.Teachings.IgnoreQueryFilters()
                .FirstOrDefaultAsync(t => t.TeachCode == teachingAddRequest.TeachCode);
        if (existingTeaching != null)
        {
            return -1;
        }

        var newTeaching = new Teaching
        {
            TeachGrade = teachingAddRequest.TeachGrade,
            TeachCode = teachingAddRequest.TeachCode,
            TeachCredits = teachingAddRequest.TeachCredits,
            TeachCapacity = teachingAddRequest.TeachCapacity,
            TeachWeekLength = teachingAddRequest.TeachWeekLength,
            TeachTheoryHours = teachingAddRequest.TeachTheoryHours,
            TeachPracticalHours = teachingAddRequest.TeachPracticalHours,
            TeachComposition = teachingAddRequest.TeachComposition,
            TeachLocation = teachingAddRequest.TeachLocation,
            TeachStatus = TeachStatus.UnRelease,
            CourseId = teachingAddRequest.CourseId,
            Remark = teachingAddRequest.Remark
        };
        await dbContext.Teachings.AddAsync(newTeaching);
        await dbContext.SaveChangesAsync();

        return newTeaching.Id;
    }

    public async Task<bool> UpdateAsync(TeachingUpdateRequest teachingUpdateRequest)
    {
        var teachings = await dbContext.Teachings
            .IgnoreQueryFilters()
            .Where(t => t.TeachCode == teachingUpdateRequest.TeachCode || t.Id == teachingUpdateRequest.Id)
            .ToListAsync();

        var conflictTeaching = teachings.FirstOrDefault(x => x.Id != teachingUpdateRequest.Id);
        if (conflictTeaching != null)
        {
            return false;
        }

        var existingTeaching = teachings.FirstOrDefault(x => x.Id == teachingUpdateRequest.Id);
        if (existingTeaching == null)
        {
            return false;
        }

        existingTeaching.Remark = teachingUpdateRequest.Remark;
        existingTeaching.TeachGrade = teachingUpdateRequest.TeachGrade;
        existingTeaching.TeachCode = teachingUpdateRequest.TeachCode;
        existingTeaching.TeachCredits = teachingUpdateRequest.TeachCredits;
        existingTeaching.TeachCapacity = teachingUpdateRequest.TeachCapacity;
        existingTeaching.TeachWeekLength = teachingUpdateRequest.TeachWeekLength;
        existingTeaching.TeachTheoryHours = teachingUpdateRequest.TeachTheoryHours;
        existingTeaching.TeachPracticalHours = teachingUpdateRequest.TeachPracticalHours;
        existingTeaching.TeachComposition = teachingUpdateRequest.TeachComposition;
        existingTeaching.TeachLocation = teachingUpdateRequest.TeachLocation;
        existingTeaching.CourseId = teachingUpdateRequest.CourseId;

        await dbContext.SaveChangesAsync();
        return true;
    }

    public async Task<PagedResult<TeachingResult>> GetTeachingPagedAsync(PagedRequest request)
    {
        var teachingPagedResult = await GetPagedAsync(request);
        var teachingList = teachingPagedResult.Data;

        // 获取教学 ID 和课程 ID
        var teachingIds = teachingList.Select(x => x.Id).ToList();
        var courseIds = teachingList.Select(x => x.CourseId).ToList();

        // 合并查询课程名称
        var courseNames = await dbContext.Courses
            .Where(x => courseIds.Contains(x.Id))
            .ToDictionaryAsync(x => x.Id, x => x.CouName);

        // 合并查询教师名称
        var teacherNames = await dbContext.TeacherTeachings
            .Where(tt => teachingIds.Contains(tt.TeachId))
            .Join(dbContext.Teachers, tt => tt.TeacherId, t => t.Id, (tt, t) => new { tt.TeachId, t.PsnId })
            .Join(dbContext.People, temp => temp.PsnId, p => p.Id, (temp, p) => new { temp.TeachId, p.PsnName })
            .GroupBy(x => x.TeachId)
            .ToDictionaryAsync(g => g.Key, g => g.Select(x => x.PsnName).Distinct().ToList());

        // 合并查询课程安排
        var schedules = await dbContext.Schedules
            .Where(schedule => teachingIds.Contains(schedule.TeachId))
            .GroupBy(schedule => schedule.TeachId)
            .ToDictionaryAsync(g => g.Key, g => g.Select(x => new ScheduleInfo
            {
                WeekDay = x.WeekDay,
                ClassNumbers = x.ClassNumbers
            }).ToList());

        // 使用投影优化结果映射
        var results = teachingList.Select(teaching => new TeachingResult
        {
            Id = teaching.Id,
            TeachGrade = teaching.TeachGrade,
            TeachCode = teaching.TeachCode,
            TeachCredits = teaching.TeachCredits,
            TeachCapacity = teaching.TeachCapacity,
            TeachWeekLength = teaching.TeachWeekLength,
            TeachTheoryHours = teaching.TeachTheoryHours,
            TeachPracticalHours = teaching.TeachPracticalHours,
            TeachComposition = teaching.TeachComposition,
            TeachLocation = teaching.TeachLocation,
            TeachStatus = teaching.TeachStatus,
            CourseId = teaching.CourseId,
            CourseName = courseNames.GetValueOrDefault(teaching.CourseId) ?? throw new InvalidOperationException(),
            TeacherNames = teacherNames.GetValueOrDefault(teaching.Id, []),
            ScheduleInfoList = schedules.GetValueOrDefault(teaching.Id, []),
            Remark = teaching.Remark,
            CreatedTime = teaching.CreatedTime,
            UpdatedTime = teaching.UpdatedTime,
            CreatedBy = teaching.CreatedBy,
            UpdatedBy = teaching.UpdatedBy,
            DelFlag = teaching.DelFlag
        }).ToList();

        // 返回分页结果
        return new PagedResult<TeachingResult>
        {
            Data = results,
            TotalRecords = teachingPagedResult.TotalRecords,
            TotalPages = teachingPagedResult.TotalPages,
            PageNumber = teachingPagedResult.PageNumber,
            PageSize = teachingPagedResult.PageSize
        };
    }

    public async Task<bool> Release(long teachingId)
    {
        var teaching = await dbContext.Teachings.FindAsync(teachingId);

        if (teaching == null)
        {
            return false;
        }

        teaching.TeachStatus = TeachStatus.Release;
        return await dbContext.SaveChangesAsync() > 0;
    }
}